//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.jf.smali;

import com.google.common.collect.Lists;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.annotation.Nonnull;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenSource;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.writer.builder.DexBuilder;
import org.jf.dexlib2.writer.io.FileDataStore;
import org.jf.util.StringUtils;

public class Smali {
    public Smali() {
    }

    public static boolean assemble(SmaliOptions options, String... input) throws IOException {
        return assemble(options, Arrays.asList(input));
    }

    public static boolean assemble(final SmaliOptions options, List<String> input) throws IOException {
        TreeSet<File> filesToProcessSet = new TreeSet();
        Iterator var3 = input.iterator();

        while(var3.hasNext()) {
            String fileToProcess = (String)var3.next();
            File argFile = new File(fileToProcess);
            if (!argFile.exists()) {
                throw new IllegalArgumentException("Cannot find file or directory \"" + fileToProcess + "\"");
            }

            if (argFile.isDirectory()) {
                getSmaliFilesInDir(argFile, filesToProcessSet);
            } else if (argFile.isFile()) {
                filesToProcessSet.add(argFile);
            }
        }

        boolean errors = false;
        final DexBuilder dexBuilder = new DexBuilder(Opcodes.forApi(options.apiLevel));
        ExecutorService executor = Executors.newFixedThreadPool(options.jobs);
        List<Future<Boolean>> tasks = Lists.newArrayList();
        Iterator var7 = filesToProcessSet.iterator();

        while(var7.hasNext()) {
            final File file = (File)var7.next();
            tasks.add(executor.submit(new Callable<Boolean>() {
                public Boolean call() throws Exception {
                    return Smali.assembleSmaliFile(file, dexBuilder, options);
                }
            }));
        }

        var7 = tasks.iterator();

        while(var7.hasNext()) {
            Future<Boolean> task = (Future)var7.next();

            while(true) {
                try {
                    try {
                        if (!(Boolean)task.get()) {
                            errors = true;
                        }
                        break;
                    } catch (ExecutionException var10) {
                        ExecutionException ex = var10;
                        throw new RuntimeException(ex);
                    }
                } catch (InterruptedException var11) {
                }
            }
        }

        executor.shutdown();
        if (errors) {
            return false;
        } else {
            dexBuilder.writeTo(new FileDataStore(new File(options.outputDexFile)));
            return true;
        }
    }

    public static boolean printTokens(SmaliOptions options, List<String> input) throws IOException {
        TreeSet<File> filesToProcessSet = new TreeSet();
        Iterator var3 = input.iterator();

        File argFile;
        while(var3.hasNext()) {
            String fileToProcess = (String)var3.next();
            argFile = new File(fileToProcess);
            if (!argFile.exists()) {
                throw new IllegalArgumentException("Cannot find file or directory \"" + fileToProcess + "\"");
            }

            if (argFile.isDirectory()) {
                getSmaliFilesInDir(argFile, filesToProcessSet);
            } else if (argFile.isFile()) {
                filesToProcessSet.add(argFile);
            }
        }

        boolean errors = false;
        Iterator var9 = filesToProcessSet.iterator();

        while(var9.hasNext()) {
            argFile = (File)var9.next();

            try {
                errors |= !printTokensForSingleFile(argFile, options);
            } catch (Exception var7) {
                Exception ex = var7;
                throw new RuntimeException(ex);
            }
        }

        return !errors;
    }

    private static void getSmaliFilesInDir(@Nonnull File dir, @Nonnull Set<File> smaliFiles) {
        File[] files = dir.listFiles();
        if (files != null) {
            File[] var3 = files;
            int var4 = files.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                File file = var3[var5];
                if (file.isDirectory()) {
                    getSmaliFilesInDir(file, smaliFiles);
                } else if (file.getName().endsWith(".smali")) {
                    smaliFiles.add(file);
                }
            }
        }

    }

    private static boolean assembleSmaliFile(File smaliFile, DexBuilder dexBuilder, SmaliOptions options) throws Exception {
        FileInputStream fis = null;

        boolean var18;
        try {
            fis = new FileInputStream(smaliFile);
            InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
            LexerErrorInterface lexer = new smaliFlexLexer(reader, options.apiLevel);
            ((smaliFlexLexer)lexer).setSourceFile(smaliFile);
            CommonTokenStream tokens = new CommonTokenStream((TokenSource)lexer);
            if (options.printTokens) {
                tokens.getTokens();

                for(int i = 0; i < tokens.size(); ++i) {
                    Token token = tokens.get(i);
                    if (token.getChannel() != 99) {
                        String tokenName;
                        if (token.getType() == -1) {
                            tokenName = "EOF";
                        } else {
                            tokenName = smaliParser.tokenNames[token.getType()];
                        }

                        System.out.println(tokenName + ": " + token.getText());
                    }
                }

                System.out.flush();
            }

            smaliParser parser = new smaliParser(tokens);
            parser.setVerboseErrors(options.verboseErrors);
            parser.setAllowOdex(options.allowOdexOpcodes);
            parser.setApiLevel(options.apiLevel);
            smaliParser.smali_file_return result = parser.smali_file();
            if (parser.getNumberOfSyntaxErrors() <= 0 && lexer.getNumberOfSyntaxErrors() <= 0) {
                CommonTree t = result.getTree();
                CommonTreeNodeStream treeStream = new CommonTreeNodeStream(t);
                treeStream.setTokenStream(tokens);
                if (options.printTokens) {
                    System.out.println(t.toStringTree());
                }

                smaliTreeWalker dexGen = new smaliTreeWalker(treeStream);
                dexGen.setApiLevel(options.apiLevel);
                dexGen.setVerboseErrors(options.verboseErrors);
                dexGen.setDexBuilder(dexBuilder);
                dexGen.smali_file();
                boolean var12 = dexGen.getNumberOfSyntaxErrors() == 0;
                return var12;
            }

            var18 = false;
        } finally {
            if (fis != null) {
                fis.close();
            }

        }

        return var18;
    }

    private static boolean printTokensForSingleFile(File smaliFile, SmaliOptions options) throws Exception {
        FileInputStream fis = null;

        boolean var12;
        try {
            fis = new FileInputStream(smaliFile);
            InputStreamReader reader = new InputStreamReader(fis, "UTF-8");
            LexerErrorInterface lexer = new smaliFlexLexer(reader, options.apiLevel);
            ((smaliFlexLexer)lexer).setSourceFile(smaliFile);
            CommonTokenStream tokens = new CommonTokenStream((TokenSource)lexer);
            tokens.fill();

            for(int i = 0; i < tokens.size(); ++i) {
                Token token = tokens.get(i);
                if (token.getChannel() != 99) {
                    String tokenName;
                    if (token.getType() == -1) {
                        tokenName = "EOF";
                    } else {
                        tokenName = smaliParser.tokenNames[token.getType()];
                    }

                    System.out.println(tokenName + "(\"" + StringUtils.escapeString(token.getText()) + "\")");
                }
            }

            System.out.flush();
            var12 = lexer.getNumberOfSyntaxErrors() == 0;
        } finally {
            if (fis != null) {
                fis.close();
            }

        }

        return var12;
    }
}
